package com.ctrip.corp.obt.shard.sql.mybatis.interceptor.compatibility.kingbase;


import java.util.Map;
import java.util.StringJoiner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.shard.sql.mybatis.interceptor.compatibility.BaseFunctionCompatibility;
import com.ctrip.corp.obt.shard.utils.PluginUtils;

import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Function;

import static com.ctrip.corp.obt.shard.sql.mybatis.interceptor.compatibility.constant.CompatibilityConstant.*;

/**
 * 函数兼容
 *
 * @author x.shen
 * @since 2023/11/26
 */
@Slf4j
public class KBFunctionCompatibility extends BaseFunctionCompatibility {
    /**
     * 通用函数存放，仅针对将不携带入参的函数替换 或 将入参去除的函数替换
     * 如：now(3) ===> now()
     *    last_insert_id() ===> lastval()
     *
     */
    public static final Map<String, SubFunction> SQL_COMMON_FUNCTION_MAP = new ConcurrentHashMap<>(100);
    /**
     * 特殊函数处理，用于有自己特定表达式函数方式
     * 如：json_search ===> json_extract(column,'$.')
     */
    public static final Map<String, SubFunction> SQL_SPECIAL_FUNCTION_MAP = new ConcurrentHashMap<>(100);

    public KBFunctionCompatibility() {
        SQL_COMMON_FUNCTION_MAP.put(FUNCTION_NOW, new SubFunction(KB_FUNCTION_NOW));
        SQL_COMMON_FUNCTION_MAP.put(FUNCTION_LAST_INSERT_ID, new SubFunction(KB_FUNCTION_LAST_INSERT_ID));
        SQL_COMMON_FUNCTION_MAP.put(FUNCTION_CURRENT_TIMESTAMP, new SubFunction(KB_FUNCTION_CURRENT_TIMESTAMP));
    }

    /**
     * 特殊函数处理，由自己的兼容器处理
     *
     * @param expression
     */
    @Override
    public void handleSpecialFunction(Function expression) {
        if (CollectionUtils.isEmpty(SQL_SPECIAL_FUNCTION_MAP)) {
            return;
        }
        // do something
    }

    public void buildFunctionsSql(PluginUtils.DSBoundSql dsBoundSql) {
        // field函数处理
        handleFieldFunction(dsBoundSql);
    }

    /**
     * field函数兼容
     * 
     * @param dsBoundSql
     */
    private void handleFieldFunction(PluginUtils.DSBoundSql dsBoundSql) {
        String originalSql = dsBoundSql.sql();
        String pattern = "\\b(FIELD|field)\\s*\\((.*?)\\)";
        Matcher matcher = Pattern.compile(pattern).matcher(originalSql);
        StringBuffer compatibleSql = new StringBuffer();
        while (matcher.find()) {
            String match = matcher.group(2);
            String[] split = match.split(",");
            // split[0] --- columnName
            StringJoiner joiner = new StringJoiner(",");
            for (int i = 0; i < split.length; i++) {
                joiner.add(split[i]);
                if (i != 0) {
                    joiner.add(String.valueOf(i));
                }
            }
            // 添加默认值
            joiner.add("0");
            matcher.appendReplacement(compatibleSql, "decode" + "(" + joiner.toString() + ")");
        }
        matcher.appendTail(compatibleSql);
        dsBoundSql.sql(compatibleSql.toString());

    }
}
